package com.lineage.server.model.Instance;

import com.lineage.config.ConfigOther;
import com.lineage.server.IdFactoryNpc;
import com.lineage.server.datatables.NpcTable;
import com.lineage.server.model.L1AttackPc;
import com.lineage.server.model.L1Character;
import com.lineage.server.model.L1GroundInventory;
import com.lineage.server.model.L1Inventory;
import com.lineage.server.model.L1Object;
import com.lineage.server.model.drop.SetDrop;
import com.lineage.server.serverpackets.S_HPMeter;
import com.lineage.server.serverpackets.S_NPCPack_Summon;
import com.lineage.server.serverpackets.S_PetMenuPacket;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.S_SkillSound;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.templates.L1Npc;
import com.lineage.server.types.Point;
import com.lineage.server.world.World;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class L1SummonInstance extends L1NpcInstance {
  private static final long serialVersionUID = 1L;
  
  private static final Log _log = LogFactory.getLog(L1SummonInstance.class);
  
  private static final int _summonTime = ConfigOther.summtime;
  
  private int _currentPetStatus;
  
  private int _checkMove;
  
  private boolean _tamed;
  
  private boolean _isReturnToNature;
  
  private static Random _random = new Random();
  
  private int _time;
  
  private int _tempModel;
  
  public boolean tamed() {
    return this._tamed;
  }
  
  public boolean noTarget() {
    if (!isAiRunning())
      startAI(); 
    switch (this._currentPetStatus) {
      case 3:
        return true;
      case 4:
        if (this._master == null || this._master.getMapId() != getMapId() || 
          getLocation().getTileLineDistance((Point)this._master.getLocation()) >= 5) {
          this._currentPetStatus = 3;
          return true;
        } 
        if (this._npcMove != null) {
          int dir = this._npcMove.targetReverseDirection(this._master.getX(), this._master.getY());
          dir = this._npcMove.checkObject(dir);
          this._npcMove.setDirectionMove(dir);
          setSleepTime(calcSleepTime(getPassispeed(), 0));
        } 
        return false;
      case 5:
        if ((Math.abs(getHomeX() - getX()) > 1 || Math.abs(getHomeY() - getY()) > 1) && this._npcMove != null) {
          int dir = this._npcMove.moveDirection(getHomeX(), getHomeY());
          if (dir == -1) {
            setHomeX(getX());
            setHomeY(getY());
          } else {
            this._npcMove.setDirectionMove(dir);
            setSleepTime(calcSleepTime(getPassispeed(), 0));
          } 
        } 
        return false;
    } 
    if (this._master == null || this._master.getMapId() != getMapId()) {
      this._currentPetStatus = 3;
      return true;
    } 
    int location = getLocation().getTileLineDistance((Point)this._master.getLocation());
    if (location > 2 && this._npcMove != null) {
      int dir2 = this._npcMove.moveDirection(this._master.getX(), this._master.getY());
      if (dir2 != -1) {
        this._checkMove = 0;
        this._npcMove.setDirectionMove(dir2);
        setSleepTime(calcSleepTime(getPassispeed(), 0));
      } else {
        this._checkMove++;
        if (this._checkMove >= 10) {
          this._checkMove = 0;
          this._currentPetStatus = 3;
          return true;
        } 
      } 
    } 
    return false;
  }
  
  public L1SummonInstance(L1Npc template, L1Character master) {
    super(template);
    this._checkMove = 0;
    this._isReturnToNature = false;
    this._time = 0;
    this._tempModel = 3;
    setId(IdFactoryNpc.get().nextId());
    set_showId(master.get_showId());
    set_time(_summonTime);
    setMaster(master);
    setX(master.getX() + _random.nextInt(5) - 2);
    setY(master.getY() + _random.nextInt(5) - 2);
    setMap(master.getMapId());
    setHeading(5);
    setLightSize(template.getLightSize());
    this._currentPetStatus = 1;
    this._tamed = false;
    World.get().storeObject((L1Object)this);
    World.get().addVisibleObject((L1Object)this);
    Iterator<L1PcInstance> iterator = World.get().getRecognizePlayer((L1Object)this).iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      onPerceive(pc);
    } 
    master.addPet(this);
    if (master instanceof L1PcInstance) {
      addMaster((L1PcInstance)master);
    } else if (master instanceof L1NpcInstance) {
      this._currentPetStatus = 1;
    } 
  }
  
  public L1SummonInstance(L1NpcInstance target, L1Character master, boolean isCreateZombie) {
    super((L1Npc)null);
    this._checkMove = 0;
    this._isReturnToNature = false;
    this._time = 0;
    this._tempModel = 3;
    setId(IdFactoryNpc.get().nextId());
    set_showId(master.get_showId());
    if (isCreateZombie) {
      int npcId = 45065;
      L1PcInstance pc = (L1PcInstance)master;
      int level = pc.getLevel();
      if (pc.isWizard()) {
        if (level >= 24 && level <= 31) {
          npcId = 81183;
        } else if (level >= 32 && level <= 39) {
          npcId = 81184;
        } else if (level >= 40 && level <= 43) {
          npcId = 81185;
        } else if (level >= 44 && level <= 47) {
          npcId = 81186;
        } else if (level >= 48 && level <= 51) {
          npcId = 81187;
        } else if (level >= 52) {
          npcId = 81188;
        } 
      } else if (pc.isElf() && level >= 48) {
        npcId = 81183;
      } 
      L1Npc template = NpcTable.get().getTemplate(npcId).clone();
      setting_template(template);
    } else {
      setting_template(target.getNpcTemplate());
      setCurrentHpDirect(target.getCurrentHp());
      setCurrentMpDirect(target.getCurrentMp());
    } 
    set_time(_summonTime);
    setMaster(master);
    setX(target.getX());
    setY(target.getY());
    setMap(target.getMapId());
    setHeading(target.getHeading());
    setLightSize(target.getLightSize());
    setPetcost(6);
    if (target instanceof L1MonsterInstance && !((L1MonsterInstance)target).is_storeDroped()) {
      SetDrop setDrop = new SetDrop();
      setDrop.setDrop(target, target.getInventory());
    } 
    setInventory(target.getInventory());
    target.setInventory((L1Inventory)null);
    this._currentPetStatus = 1;
    this._tamed = true;
    Iterator<L1NpcInstance> iterator = master.getPetList().values().iterator();
    while (iterator.hasNext()) {
      L1NpcInstance each = iterator.next();
      each.targetRemove(target);
    } 
    target.deleteMe();
    World.get().storeObject((L1Object)this);
    World.get().addVisibleObject((L1Object)this);
    Iterator<L1PcInstance> iterator2 = World.get().getRecognizePlayer((L1Object)this).iterator();
    while (iterator2.hasNext()) {
      L1PcInstance pc2 = iterator2.next();
      onPerceive(pc2);
    } 
    master.addPet(this);
    if (master instanceof L1PcInstance)
      addMaster((L1PcInstance)master); 
  }
  
  public void receiveDamage(L1Character attacker, int damage) {
    this.ISASCAPE = false;
    if (getCurrentHp() > 0) {
      if (damage > 0) {
        setHate(attacker, 0);
        removeSkillEffect(66);
        removeSkillEffect(212);
        if (!isExsistMaster()) {
          this._currentPetStatus = 1;
          setTarget(attacker);
        } 
      } 
      if (attacker instanceof L1PcInstance && damage > 0) {
        L1PcInstance player = (L1PcInstance)attacker;
        player.setPetTarget(this);
      } 
      int newHp = getCurrentHp() - damage;
      if (newHp <= 0) {
        Death(attacker);
      } else {
        setCurrentHp(newHp);
      } 
    } else if (!isDead()) {
      _log.error("NPC hp减少处理失败 可能原因: 初始hp为0(" + getNpcId() + ")");
      Death(attacker);
    } 
  }
  
  public synchronized void Death(L1Character lastAttacker) {
    if (!isDead()) {
      setDead(true);
      setCurrentHp(0);
      setStatus(8);
      getMap().setPassable((Point)getLocation(), true);
      deleteMe();
    } 
  }
  
  public synchronized void returnToNature() {
    this._isReturnToNature = true;
    if (!this._tamed) {
      getMap().setPassable((Point)getLocation(), true);
      L1Inventory targetInventory = null;
      if (this._master != null && this._master.getInventory() != null)
        targetInventory = this._master.getInventory(); 
      List<L1ItemInstance> items = this._inventory.getItems();
      Iterator<L1ItemInstance> iterator = items.iterator();
      while (iterator.hasNext()) {
        L1ItemInstance item = iterator.next();
        if (targetInventory != null) {
          if (this._master.getInventory().checkAddItem(item, item.getCount()) == 0) {
            this._inventory.tradeItem(item, item.getCount(), targetInventory);
            ((L1PcInstance)this._master)
              .sendPackets((ServerBasePacket)new S_ServerMessage(143, getName(), item.getLogName()));
            continue;
          } 
          item.set_showId(get_showId());
          L1GroundInventory l1GroundInventory1 = World.get().getInventory(getX(), getY(), getMapId());
          this._inventory.tradeItem(item, item.getCount(), (L1Inventory)l1GroundInventory1);
          continue;
        } 
        item.set_showId(get_showId());
        L1GroundInventory l1GroundInventory = World.get().getInventory(getX(), getY(), getMapId());
        this._inventory.tradeItem(item, item.getCount(), (L1Inventory)l1GroundInventory);
      } 
      deleteMe();
    } else {
      liberate();
    } 
  }
  
  public synchronized void deleteMe() {
    if (this._master != null)
      this._master.removePet(this); 
    if (this._destroyed)
      return; 
    if (!this._tamed && !this._isReturnToNature)
      broadcastPacketX8((ServerBasePacket)new S_SkillSound(getId(), 169)); 
    super.deleteMe();
  }
  
  public void liberate() {
    L1MonsterInstance monster = new L1MonsterInstance(getNpcTemplate());
    monster.setId(IdFactoryNpc.get().nextId());
    monster.setX(getX());
    monster.setY(getY());
    monster.setMap(getMapId());
    monster.setHeading(getHeading());
    monster.set_storeDroped(true);
    monster.setInventory(getInventory());
    setInventory((L1Inventory)null);
    monster.setCurrentHpDirect(getCurrentHp());
    monster.setCurrentMpDirect(getCurrentMp());
    monster.setExp(0L);
    deleteMe();
    World.get().storeObject((L1Object)monster);
    World.get().addVisibleObject((L1Object)monster);
  }
  
  public void setTarget(L1Character target) {
    if (target != null && (
      this._currentPetStatus == 1 || this._currentPetStatus == 2 || this._currentPetStatus == 5))
      setHate(target, 0); 
    if (!isAiRunning())
      startAI(); 
  }
  
  public void setMasterTarget(L1Character target) {
    if (target != null && (this._currentPetStatus == 1 || this._currentPetStatus == 5))
      setHate(target, 10); 
    if (!isAiRunning())
      startAI(); 
  }
  
  public void onAction(L1PcInstance player) {
    if (!isAiRunning())
      startAI(); 
    if (player == null)
      return; 
    L1Character cha = getMaster();
    if (cha == null)
      return; 
    L1PcInstance master = (L1PcInstance)cha;
    if (master.isTeleport())
      return; 
    if (master.equals(player)) {
      L1AttackPc l1AttackPc1 = new L1AttackPc(player, this);
      l1AttackPc1.action();
      return;
    } 
    if ((isSafetyZone() || player.isSafetyZone()) && isExsistMaster()) {
      L1AttackPc l1AttackPc1 = new L1AttackPc(player, this);
      l1AttackPc1.action();
      return;
    } 
    if (player.checkNonPvP(player, this))
      return; 
    L1AttackPc l1AttackPc = new L1AttackPc(player, this);
    if (l1AttackPc.calcHit())
      l1AttackPc.calcDamage(); 
    l1AttackPc.action();
    l1AttackPc.commit();
  }
  
  public void onTalkAction(L1PcInstance player) {
    if (isDead())
      return; 
    if (this._master.equals(player))
      player.sendPackets((ServerBasePacket)new S_PetMenuPacket(this, 0)); 
  }
  
  public void onFinalAction(L1PcInstance player, String action) {
    if (!isAiRunning())
      startAI(); 
    int status = Integer.parseInt(action);
    switch (status) {
      case 0:
      case 6:
        Death((L1Character)null);
        return;
    } 
    Object[] petList = this._master.getPetList().values().toArray();
    Object[] array;
    int length = (array = petList).length;
    int i = 0;
    while (i < length) {
      Object petObject = array[i];
      if (petObject instanceof L1SummonInstance) {
        L1SummonInstance summon = (L1SummonInstance)petObject;
        summon.set_currentPetStatus(status);
      } 
      i++;
    } 
  }
  
  public void onPerceive(L1PcInstance perceivedFrom) {
    try {
      if (perceivedFrom.get_showId() != get_showId())
        return; 
      perceivedFrom.addKnownObject((L1Object)this);
      perceivedFrom.sendPackets((ServerBasePacket)new S_NPCPack_Summon(this, perceivedFrom));
      if (getMaster() != null && perceivedFrom.getId() == getMaster().getId())
        perceivedFrom.sendPackets((ServerBasePacket)new S_HPMeter(getId(), 100 * getCurrentHp() / getMaxHp())); 
      if (!isAiRunning())
        startAI(); 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public void onItemUse() {
    if (!isActived())
      useItem(1, 100); 
    if (getCurrentHp() * 100 / getMaxHp() < 40)
      useItem(0, 100); 
  }
  
  public void onGetItem(L1ItemInstance item) {
    if (getNpcTemplate().get_digestitem() > 0)
      setDigestItem(item); 
    Arrays.sort(L1NpcInstance.healPotions);
    Arrays.sort(L1NpcInstance.haestPotions);
    if (Arrays.binarySearch(L1NpcInstance.healPotions, item.getItem().getItemId()) >= 0) {
      if (getCurrentHp() != getMaxHp())
        useItem(0, 100); 
    } else if (Arrays.binarySearch(L1NpcInstance.haestPotions, item.getItem().getItemId()) >= 0) {
      useItem(1, 100);
    } 
  }
  
  public void setCurrentHp(int i) {
    if (!isAiRunning())
      startAI(); 
    int currentHp = Math.min(i, getMaxHp());
    if (getCurrentHp() == currentHp)
      return; 
    setCurrentHpDirect(currentHp);
    if (this._master instanceof L1PcInstance) {
      int hpRatio = 100 * currentHp / getMaxHp();
      L1PcInstance master = (L1PcInstance)this._master;
      master.sendPackets((ServerBasePacket)new S_HPMeter(getId(), hpRatio));
    } 
  }
  
  public void setCurrentMp(int i) {
    int currentMp = Math.min(i, getMaxMp());
    if (getCurrentMp() == currentMp)
      return; 
    setCurrentMpDirect(currentMp);
  }
  
  public void set_currentPetStatus(int i) {
    this._currentPetStatus = i;
    set_tempModel();
    switch (this._currentPetStatus) {
      case 5:
        setHomeX(getX());
        setHomeY(getY());
        break;
      case 3:
        allTargetClear();
        break;
    } 
    if (!isAiRunning())
      startAI(); 
  }
  
  public int get_currentPetStatus() {
    return this._currentPetStatus;
  }
  
  public boolean isExsistMaster() {
    boolean isExsistMaster = true;
    if (getMaster() != null) {
      String masterName = getMaster().getName();
      if (World.get().getPlayer(masterName) == null)
        isExsistMaster = false; 
    } 
    return isExsistMaster;
  }
  
  public int get_time() {
    return this._time;
  }
  
  public void set_time(int time) {
    this._time = time;
  }
  
  public void set_tempModel() {
    this._tempModel = this._currentPetStatus;
  }
  
  public void get_tempModel() {
    this._currentPetStatus = this._tempModel;
  }
  
  public void checkAI() {
    if (!isAiRunning()) {
      String masterName = null;
      if (this._master != null)
        masterName = this._master.getName(); 
      _log
        .error("召唤物AI没有运行，自动重新运行。召唤兽：" + getNpcTemplate().get_name() + " 主人：" + masterName);
      startAI();
    } 
  }
}
